package com.icloud.wallet.boot.schedule;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.icloud.common.cache.constants.CacheConstants;
import com.icloud.common.cache.service.RedisService;
import com.icloud.common.database.enums.*;
import com.icloud.common.database.mapper.AppCustomerMapper;
import com.icloud.common.database.model.CustomerWallet;
import com.icloud.common.database.model.RedPacket;
import com.icloud.common.database.model.TWalletJournal;
import com.icloud.wallet.boot.service.CustomerWalletService;
import com.icloud.wallet.boot.service.ITWalletJournalService;
import com.icloud.wallet.boot.service.RedPacketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class RedPacketTask {
    @Autowired
    private RedisService redisService;
    @Autowired
    private RedPacketService redPacketService;
    @Autowired
    private AppCustomerMapper appCustomerMapper;
    @Autowired
    private CustomerWalletService customerWalletService;
    @Autowired
    private ITWalletJournalService itWalletJournalService;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void refund(){
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime yesterdayNow = now.minusDays(1);
        //LocalDateTime yesterdayNow = now.minusMinutes(1);
        LambdaQueryWrapper<RedPacket> rpQuery = new LambdaQueryWrapper<>();
        rpQuery.lt(RedPacket::getCreatedAt, yesterdayNow);
        rpQuery.eq(RedPacket::getHandleState, RedPacketHandleStateEnum.UNHANDLED.getCode());
        List<RedPacket> rpList = redPacketService.list(rpQuery);
        if(CollectionUtils.isEmpty(rpList)){
            log.debug("无过期红包");
            return;
        }
        // 删除过期红包的缓存
        rpList.forEach(rp->{
            String key = CacheConstants.CACHE_RED_PACKET + rp.getId();
            redisService.del(key);
        });

        List<RedPacket> unList = rpList.stream().filter(rp->rp.getAmount().compareTo(rp.getAmtReceived())>0).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(unList)){
            log.debug("无过期未领完红包");
            return;
        }
        // 需要退款的红包创建人
        Map<Long, List<RedPacket>> refundMap = unList.stream().collect(Collectors.groupingBy(RedPacket::getCreatedId));

        LambdaQueryWrapper<CustomerWallet> cwQuery = new LambdaQueryWrapper<>();
        cwQuery.in(CustomerWallet::getCustomerId, refundMap.keySet());
        List<CustomerWallet> cwList = customerWalletService.list(cwQuery);

        // 批量生成流水, 批量更新钱包余额
        List<TWalletJournal> journalList = new ArrayList<>();
        List<RedPacket> rpUpdateList = new ArrayList<>();
        List<CustomerWallet> cwUpdateList = new ArrayList<>();
        cwList.forEach(cw->{
            Long customerId = cw.getCustomerId();
            BigDecimal before = cw.getBcpc();
            List<RedPacket> rfrpList = refundMap.get(customerId);
            if(!CollectionUtils.isEmpty(rfrpList)) {
                rfrpList.forEach(rfrp->{
                    Long rfrpId = rfrp.getId();
                    BigDecimal amount = rfrp.getAmount();
                    BigDecimal after = before.add(amount);
                    CustomerWallet update = CustomerWallet.builder()
                            .id(cw.getId())
                            .bcpc(after)
                            .build();
                    cwUpdateList.add(update);

                    RedPacket rpUpdate = new RedPacket();
                    rpUpdate.setId(rfrpId);
                    rpUpdate.setHandleState(RedPacketHandleStateEnum.EXPIRE.getCode());
                    rpUpdateList.add(rpUpdate);

                    TWalletJournal journal = TWalletJournal.builder()
                            .customerId(customerId)
                            .journalType(JournalTypeEnum.REFUND_RED_PKT.getCode())
                            .beforeBalance(before)
                            .amount(amount)
                            .afterBalance(after)
                            .currency(CurrencyEnum.BCPC.getCode())
                            .direction(DirectionEnum.DEBIT.getCode())
                            .journalState(JournalStateEnum.FINISHED.getCode())
                            .remark("红包退款流水,红包Id:"+rfrpId)
                            .createdId(customerId)
                            .updatedId(customerId)
                            .build();
                    journalList.add(journal);
                });
            }
        });
        if(!CollectionUtils.isEmpty(journalList)) {
            itWalletJournalService.saveBatch(journalList);
        }
        if(!CollectionUtils.isEmpty(cwUpdateList)) {
            customerWalletService.updateBatchById(cwUpdateList);
        }
        if(!CollectionUtils.isEmpty(rpUpdateList)){
            redPacketService.updateBatchById(rpUpdateList);
        }
    }
}
